using admin.core.Entities.App;
using admin.core.Repositories;
using MediatR;
using admin.application.Notifications;
using System.Data;
using Dapper;
using System.Linq;

namespace admin.application.Services;

public class AppRoleServices : IAppRoleServices
{
    private readonly IRepository<AppRole> _roleRepo;
    private readonly IRepository<AppPermission> _permissionRepo;
    private readonly IMediator _mediator;
    private readonly IDbConnection _dbConnection;

    public AppRoleServices(IRepository<AppRole> roleRepo, IRepository<AppPermission> permissionRepo, IMediator mediator, IDbConnection dbConnection)
    {
        _roleRepo = roleRepo;
        _permissionRepo = permissionRepo;
        _mediator = mediator;
        _dbConnection = dbConnection;
    }

    public async Task<AppRole> CreateRoleAsync(AppRole role)
    {
        await _roleRepo.AddAsync(role);
        await _mediator.Publish(new RoleCreatedNotification(new RoleCreatedEvent(role.Id)));
        return role;
    }

    public async Task<AppRole?> UpdateRoleAsync(Guid id, AppRole role)
    {
        var entity = await _roleRepo.GetByIdAsync(id);
        if (entity == null) return null;
        entity.RoleName = role.RoleName;
        entity.DataScope = role.DataScope;
        await _roleRepo.UpdateAsync(entity);
        return entity;
    }

    public async Task DeleteRoleAsync(Guid id)
    {
        var entity = await _roleRepo.GetByIdAsync(id);
        if (entity != null)
        {
            entity.IsDeleted = true;
            await _roleRepo.UpdateAsync(entity);
        }
    }

    public async Task EnableRoleAsync(Guid id)
    {
        var entity = await _roleRepo.GetByIdAsync(id) ?? throw new Exception("角色不存在");
        if (entity.IsActived)
            throw new Exception("角色已是启用状态");
        entity.IsActived = true;
        await _roleRepo.UpdateAsync(entity);
    }

    public async Task DisableRoleAsync(Guid id)
    {
        var entity = await _roleRepo.GetByIdAsync(id) ?? throw new Exception("角色不存在");
        if (!entity.IsActived)
            throw new Exception("角色已是禁用状态");
        entity.IsActived = false;
        await _roleRepo.UpdateAsync(entity);
    }

    public async Task AssignPermissionAsync(Guid roleId, Guid permissionId)
    {
        var sql = "INSERT INTO \"AppPermissionAppRole\" (\"PermissionsId\", \"RolesId\") VALUES (@PermissionId, @RoleId) ON CONFLICT DO NOTHING;";
        await _dbConnection.ExecuteAsync(sql, new { PermissionId = permissionId, RoleId = roleId });
    }

    public async Task RemovePermissionAsync(Guid roleId, Guid permissionId)
    {
        var sql = "DELETE FROM \"AppPermissionAppRole\" WHERE \"RolesId\" = @RoleId AND \"PermissionsId\" = @PermissionId;";
        await _dbConnection.ExecuteAsync(sql, new { RoleId = roleId, PermissionId = permissionId });
    }

    public async Task<List<AppRole>> GetAllRolesAsync()
    {
        var roles = await _roleRepo.GetAllAsync();
        return roles.Where(r => !r.IsDeleted)
                    .OrderBy(r => r.CreatedAt)
                    .ToList();
    }

    public async Task<List<AppPermission>> GetRolePermissionsAsync(Guid roleId)
    {
        var role = await _roleRepo.GetByIdAsync(roleId);
        if (role == null)
            throw new Exception("角色不存在");
        var sql = @"SELECT p.* FROM ""AppPermission"" p
                    INNER JOIN ""AppPermissionAppRole"" pr ON p.""Id"" = pr.""PermissionsId""
                    WHERE pr.""RolesId"" = @RoleId AND p.""IsDeleted"" = false";
        var permissions = (await _dbConnection.QueryAsync<AppPermission>(sql, new { RoleId = roleId })).ToList();
        return permissions;
    }
}
